import java.awt.*;
import java.awt.event.*;
import java.util.function.Consumer;
import javax.swing.*;

/**
 * 标准型计算器类
 */
public class StandardCalc extends JFrame implements ActionListener {
    private final String[] KEYS = {"*", "/", "7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "|x|", "0", ".", "=", "1/x"};
    private final String[] COMMAND = {"Back", "C"};
    private final JButton[] keys = new JButton[KEYS.length];
    private final JButton[] commands = new JButton[COMMAND.length];
    private final JTextField resultText = new JTextField("0");
    private boolean firstDigit = true;
    private double resultNum = 0.0;
    private String operator = "=";
    private boolean operateValidFlag = true;
//    StringBuffer sb = new StringBuffer();
//    String vl = null;

    private JComboBox<String> initCombo(String[] items, Consumer<ItemEvent> consumerEvent) {
        JComboBox<String> combo = new JComboBox<>(items);
        combo.setBounds(0, 10, 50, 25);
        combo.setToolTipText("Theme");
        combo.setCursor(new Cursor(Cursor.HAND_CURSOR));
        combo.addItemListener(consumerEvent::accept);
        this.add(combo);

        return combo;
    }

    public StandardCalc() {
        //keys 18   commands  2
        Consumer<ItemEvent> themeSwitchEventConsumer = event -> {
            if (event.getStateChange() != ItemEvent.SELECTED) return;

            String selectedTheme = (String) event.getItem();
            //keys 18   commands  2
            switch (selectedTheme) {
                case "Traditional" -> {
                    this.getContentPane().setBackground(null);
                    for (int i = 0; i < 18; i++) {
                        keys[i].setBackground(null);
                        keys[i].setForeground(Color.BLACK);
                    }
                    for (int i = 0; i < 2; i++) {
                        commands[i].setBackground(null);
                        commands[i].setForeground(Color.BLACK);
                    }
                }
                case "Colorful" -> {
                    final Color fc = new Color(0x9966CC);
                    this.getContentPane().setBackground(fc);
                    for (int i = 0; i < 18; i++) {
                        final Color tmpc = new Color(255 - i * 10, 255, 255);
                        keys[i].setBackground(tmpc);
                        keys[i].setForeground(Color.BLACK);
                    }
                    for (int i = 0; i < 2; i++) {
                        final Color tmpc = new Color(255, 255, 155);
                        commands[i].setBackground(tmpc);
                        commands[i].setForeground(Color.BLACK);
                    }
                }
                case "Night" -> {
                    final Color secondaryDarkColor = new Color(171, 171, 171);
                    final Color my_white = new Color(0xFDFDFD);
                    this.getContentPane().setBackground(new Color(68, 68, 68));
                    for (int i = 0; i < 18; i++) {
                        keys[i].setBackground(secondaryDarkColor);
                        keys[i].setForeground(my_white);
                    }
                    for (int i = 0; i < 2; i++) {
                        commands[i].setBackground(secondaryDarkColor);
                        commands[i].setForeground(my_white);
                    }
                }
            }
        };
        JComboBox<String> comboTheme = initCombo(new String[]{"Traditional", "Colorful", "Night"}, themeSwitchEventConsumer);
        setTitle("标准型");
        this.setBackground(Color.LIGHT_GRAY);
        this.setTitle("ZNBCalculator:Standard Caculator");
        this.setLocation(500, 300);
        this.setSize(500, 500);
        this.setResizable(false);
        JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        JMenu menu = new JMenu("功能");
        menuBar.add(menu);
        menuBar.add(comboTheme);
        JMenuItem menuItem = new JMenuItem("标准型");
        menu.add(menuItem);
        JMenuItem menuItem_1 = new JMenuItem("科学型");
        menu.add(menuItem_1);
        JMenuItem menuItem_2 = new JMenuItem("矩阵");
        menu.add(menuItem_2);
        menuItem_1.addActionListener(arg0 -> {
                    ScentificCalc science = new ScentificCalc();
                    science.setVisible(true);
                }
        );
        menuItem_2.addActionListener(arg0 -> {
                    ZNBCalculator calc = new ZNBCalculator();
                    calc.setVisible(true);
                }
        );
        resultText.setHorizontalAlignment(JTextField.RIGHT);
        resultText.setBackground(Color.white);
        resultText.setFont(new Font("TimesRoman", Font.BOLD, 46));
        JPanel PPanel = new JPanel();
        PPanel.setLayout(new GridLayout(5, 4, 3, 3));
        for (int i = 0; i < COMMAND.length; i++) {
            commands[i] = new JButton(COMMAND[i]);
            PPanel.add(commands[i]);
            commands[i].setFont(new Font("Courir", Font.PLAIN, 20));
        }
        for (int i = 0; i < KEYS.length; i++) {
            keys[i] = new JButton(KEYS[i]);
            PPanel.add(keys[i]);
            keys[i].setFont(new Font("Courir", Font.ITALIC, 20));
        }
        JPanel panel1 = new JPanel();
        panel1.setLayout(new BorderLayout(3, 3));
        panel1.add("Center", PPanel);
        JPanel top = new JPanel();
        top.setLayout(new BorderLayout());
        top.add("Center", resultText);

        getContentPane().setLayout(new BorderLayout(3, 5));
        getContentPane().add("North", top);
        getContentPane().add("Center", panel1);
        for (int i = 0; i < KEYS.length; i++) {
            keys[i].addActionListener(this);
        }
        for (int i = 0; i < COMMAND.length; i++) {
            commands[i].addActionListener(this);
        }
    }

    public void actionPerformed(ActionEvent e) {
        String label = e.getActionCommand();
        if (label.equals(COMMAND[0])) {
            handleBack();
        } else if (label.equals(COMMAND[1])) {
            handleC();
        } else if ("0123456789.".contains(label)) {
            handleNumber(label);
        } else
            handleOperator(label);
    }

    private void handleBack() {
        String text = resultText.getText();
        int i = text.length();
        if (i > 0) {
            text = text.substring(0, i - 1);
            if (text.length() == 0) {
                resultText.setText("0");
                firstDigit = true;
                operator = "=";
            } else
                resultText.setText(text);
        }
    }

    private void handleNumber(String key) {
        if (firstDigit) {
            resultText.setText(key);
        } else if ((key.equals(".")) && (!resultText.getText().contains("."))) {
            resultText.setText(resultText.getText() + ".");
        } else if (!key.equals(".")) {
            resultText.setText(resultText.getText() + key);
        }
        firstDigit = false;
    }

    private void handleC() {
        resultText.setText("0");
        firstDigit = true;
        operator = "=";
    }

    private void handleOperator(String key) {
        switch (operator) {
            case "/":
                if (getNumberFromText() == 0.0) {
                    operateValidFlag = false;
                    resultText.setText("除数不能为零");
                } else
                    resultNum /= getNumberFromText();
                break;
            case "1/x":
                if (resultNum == 0.0) {
                    operateValidFlag = false;
                    resultText.setText("零没有倒数");
                } else
                    resultNum = 1 / resultNum;
                break;
            case "+":
                resultNum += getNumberFromText();
                break;
            case "-":
                resultNum -= getNumberFromText();
                break;
            case "*":
                resultNum *= getNumberFromText();
                break;
            case "|x|":
                resultNum = Math.abs(resultNum);
                break;
            case "=":
                resultNum = getNumberFromText();
                break;
        }
        if (operateValidFlag) {
            long t1;
            double t2;
            t1 = (long) resultNum;
            t2 = resultNum - t1;
            if (t2 == 0) {
                resultText.setText(String.valueOf(t1));
            } else {
                resultText.setText(String.valueOf(resultNum));
            }
        }
        operator = key;
        firstDigit = true;
        operateValidFlag = true;
    }

    private double getNumberFromText() {
        double result = 0;
        try {
            result = Double.parseDouble(resultText.getText());
        } catch (NumberFormatException ignored) {
        }
        return result;
    }

    public static void main(String[] args) {
        StandardCalc application = new StandardCalc();
        application.setVisible(true);
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
